#include <seminix/stackprotector.h>
#include <seminix/printk.h>
#include <seminix/smp.h>
#include <seminix/irqflags.h>
#include <seminix/string.h>

#ifdef CONFIG_STACKPROTECTOR
/*
 * Called when gcc's -fstack-protector feature is used, and
 * gcc detects corruption of the on-stack canary value
 */
__visible void __stack_chk_fail(void)
{
    panic("stack-protector: Kernel stack is corrupted in: %pB",
        __builtin_return_address(0));
}
#endif

void panic(const char *fmt, ...)
{
    static char buf[1024];
    va_list args;
    long len;

    local_irq_disable();

    va_start(args, fmt);
    len = vscnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    if (len && buf[len - 1] == '\n')
        buf[len - 1] = '\0';

    pr_emerg("---[ start Kernel panic - not syncing: %s ]---\n", buf);

    /*
     * Note smp_send_stop is the usual smp shutdown function, which
     * unfortunately means it may not be hardened to work in a
     * panic situation.
     */
    smp_send_stop();
    pr_emerg("---[ end Kernel panic - not syncing: %s ]---\n", buf);
    for (;;)
        cpu_relax();
}

__noreturn void __assert_fail(const char *expr, const char *file, int line, const char *func)
{
    panic("Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
    unreachable();
}
